{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "izw5kory4U6I"
   },
   "source": [
    "# SciPy 2024\n",
    "\n",
    "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/SciPy_2024.ipynb)\n",
    "\n",
    "The notebook contains source code for the presentation at SciPy 2024 - [Bridging the gap between Earth Engine and the Scientific Python Ecosystem](https://cfp.scipy.org/2024/talk/AJMBCU/).\n",
    "\n",
    "![](https://cfp.scipy.org/media/2024/submissions/AJMBCU/gee_scipy_t6zuVvH.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "49MjBnVa4U6L"
   },
   "source": [
    "## Install packages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "UiIxS5Vi4U6L"
   },
   "outputs": [],
   "source": [
    "%pip install geemap geopandas dask-ee pydeck xee hypercoast pyvista mapclassify"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "cgIJI0mw4U6M"
   },
   "source": [
    "## Import libraries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "98RvuE464U6M"
   },
   "outputs": [],
   "source": [
    "import ee\n",
    "import geemap"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "uE7GnkZc77Pj",
    "outputId": "9f6484e3-c229-4067-ff51-83939a004397"
   },
   "outputs": [],
   "source": [
    "def in_colab_shell():\n",
    "    \"\"\"Tests if the code is being executed within Google Colab.\"\"\"\n",
    "    import sys\n",
    "\n",
    "    if \"google.colab\" in sys.modules:\n",
    "        return True\n",
    "    else:\n",
    "        return False"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "o2Z9FS_64U6M"
   },
   "source": [
    "## Authenticate Earth Engine"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "WE_FOiaL4U6N",
    "outputId": "fddfff6f-a0d7-48a7-e9e0-395f657d8d92"
   },
   "outputs": [],
   "source": [
    "EE_PROJECT_ID = \"YOUR-PROJECT-ID\"  # Change the project ID to your own"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "Aqe8C1514U6N",
    "outputId": "4e8822f4-a4c2-48f3-f529-b50de2b9ef8d"
   },
   "outputs": [],
   "source": [
    "ee.Authenticate()\n",
    "ee.Initialize(project=EE_PROJECT_ID)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "VvM31zPD4U6O"
   },
   "source": [
    "## To Pandas DataFrame\n",
    "\n",
    "We can convert an Earth Engine FeatureCollection to a Pandas DataFrame. First, let's add an `ee.Image` and a `ee.FeatureCollection` to the map."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 621,
     "referenced_widgets": [
      "157a5590d2c44773af40eb8970adfbf2",
      "003119b4bbbd42eea29b1dbc8e85b92f",
      "6d6906278e104cd58b78bbfd22e8801f",
      "ed718d8909954a46bf703ee74d150fe2",
      "4f2a36b9d9bf4d2d9011e0ba8a7aebb5",
      "a856a349552540a99c8a75b75062f501",
      "e3aeba07d4414d999820d7576133a62a",
      "7e1811cf426f488fbe3983a75f352d1c",
      "c2137bf92d814ce6b6385445d0d64acd",
      "ce558c27dbcd48f796a747d0006aeda4",
      "7f2e2cdcb5c04440bc3372379eebe3a0",
      "74e8681c9f5646b4bbb19d3a9924e943",
      "1457ba723d034a5fa9d44c908980b163",
      "9190432a78ef42319ee203548e3de0fe",
      "0c9a9a8e8a8b4825aadd4c6c335e0aa4",
      "2bb7522d2dea412098a5534efadc3dbd",
      "262064959e654579afcd37a6e47077ef",
      "f9b15b1ce9534ef09658914b1d46fe52",
      "84c8359dd4e04c499bb2f1fba8186da0",
      "2774840621854a648707aa3975ab042c",
      "41ccf7106e0d4d39a733f7f9f93dddcb",
      "d6776559fa36402787c6fef66ba170fc",
      "30ca4c25d0654584b10b7ca08b340b3d",
      "cd90317730994dfeb735ed0a05b05086",
      "8467b151908f4f2bb36767644e6c1cd7",
      "5e6247de599742b78f8895ba44f279bf"
     ]
    },
    "id": "MLFLpWLl4U6O",
    "outputId": "d8116209-e186-418b-9866-41dca7cc8167"
   },
   "outputs": [],
   "source": [
    "m = geemap.Map(center=[40, -100], zoom=4)\n",
    "dem = ee.Image(\"USGS/SRTMGL1_003\")\n",
    "dem_vis = {\n",
    "    \"min\": 0,\n",
    "    \"max\": 4000,\n",
    "    \"palette\": [\"006633\", \"E5FFCC\", \"662A00\", \"D8D8D8\", \"F5F5F5\"],\n",
    "}\n",
    "m.add_layer(dem, dem_vis, \"SRTM DEM\", True, 0.6)\n",
    "states = ee.FeatureCollection(\"TIGER/2018/States\").filterBounds(\n",
    "    ee.Geometry.BBox(-127, 23, -66, 50)\n",
    ")\n",
    "style = {\"fillColor\": \"00000000\"}\n",
    "m.add_layer(states.style(**style), {}, \"US States\")\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "XtRAeHMq4U6O"
   },
   "source": [
    "We can use zone statistics to calculate the mean elevation for each US state. The result can be returned as an `ee.FeatureCollection`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "zhbsVnwU4U6O",
    "outputId": "54f0543b-81b3-4aa2-94cb-423f737fd66d"
   },
   "outputs": [],
   "source": [
    "dem_stats = geemap.zonal_stats(\n",
    "    dem, states, stats_type=\"MEAN\", scale=1000, return_fc=True, verbose=False\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "XRBWt64l4U6O"
   },
   "source": [
    "Next, we can convert the `ee.FeatureCollection` to a Pandas DataFrame using the `ee_to_df()` function, which uses `ee.data.computeFeatures()` under the hood."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 206
    },
    "id": "gsFiWm0i4U6O",
    "outputId": "36de8606-be8b-4555-bd94-7f81695779e9"
   },
   "outputs": [],
   "source": [
    "dem_df = geemap.ee_to_df(dem_stats)\n",
    "dem_df.sort_values(\"mean\", ascending=False).head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "PkxNVQz84U6P"
   },
   "source": [
    "Create a bar chart to show the mean elevation for each state."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 517
    },
    "id": "cpvrVoKV4U6P",
    "outputId": "93c88e94-8f60-4c95-c3f2-2e908d2bf741"
   },
   "outputs": [],
   "source": [
    "geemap.bar_chart(\n",
    "    dem_df,\n",
    "    x=\"NAME\",\n",
    "    y=\"mean\",\n",
    "    x_label=\"State\",\n",
    "    y_label=\"Mean Elevation (m)\",\n",
    "    title=\"Average Elevation by State\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "BM-9KoQe4U6P"
   },
   "source": [
    "The `zonal_stats()` function above is a simple example of how to calculate zonal statistics based a vector data and a continuous raster image. For categorical raster images, we can use the `zonal_stats_by_group()` to calculate the total area or percentage of each category within each zone.\n",
    "\n",
    "First, let's add a land cover image to the map."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 621,
     "referenced_widgets": [
      "66b002e622b04f319afb1386e5ee13c1",
      "4d6181be8c4540d4ad6eb98bfcb1988d",
      "b5c6db385ae844c3bc2c23f5515ee2ad",
      "c9f1ebde617946bdb14fc4b163ded8e4",
      "b100f8164f6a40ae835dd9aaca8efe80",
      "e4d9b115ae034585bf3167021c557aae",
      "e9cc50a96e374e30bc1c142d5f565ebd",
      "8f603ddaec124982a2f29db8f9057508",
      "cecca49590b84c5492f24eba13e71fd1",
      "1dac0350acec4a8f829c5bea579c4dee",
      "744334a4da794dfdba204dd9373091b2",
      "bcf0e153815044c5a2f4868f41c703f5",
      "1f1ecb7ce751410baaea23cb6f4d60a6",
      "a7d0ee2f2bdc4033ac1938262bf1e1c1",
      "ffd9649ee36a4d3bb9c2cbaa2bca86ff",
      "2f59b632bb2547b5837c45f2e8a3d940",
      "923829497df44e4ab386d2068f8bc280",
      "d3934dd53f444866996b5b1e9d6fbad5",
      "da9e98b7589148448b88c7ea9ac6d0af",
      "1bbb0383b9ef4b88a278693c61e271ef",
      "acfba9731b2945f9affc46151320f4f5",
      "123b8eea25f7469fa0785657dfd829e0",
      "99533f4a01bf49979da188eb20650395",
      "3bad3dd45441495a8226ad97b38c00ea",
      "6e1af56e25d3456aa0e34bbdfb59d46f",
      "626847323de349d4930b4661d26ba4c5",
      "cb12f1fdcb55472e8f7fbbbc72255eea",
      "721a1d0f6b9c443ba9a0e055e68343fc",
      "5a1dabd3730b4a85bcc99fbe848b081e",
      "85cc16071f67499788b49c2f8c95afa7",
      "a13bd2eab9fb46f4b72f87fb6210fa9b",
      "5e974a7b48454c5bb9de1faf2c3eea68",
      "975f6768764547f790edea3c10bd7bc8",
      "0e602b26e7e84c4cb3218b6fde3ad44d",
      "32b48b7ab2d74c73b5336dccd3fac182",
      "9ca0160e9af54d8592ad659bff450638",
      "35254e0942de45ccba9f62d2cdcf7449",
      "85f23a6b0530496a8c478133cb596689",
      "60ecf69793eb45c6be6bf14d8a6ade8c",
      "600db0ffb00d4249bc708770f4758b94",
      "6ff38cc61933490aa3921fe761149860",
      "029601c0d3274312b242e5d76f47b55a",
      "351e8937e3c3499d95590903dcc50ba9"
     ]
    },
    "id": "x6gPzmug4U6P",
    "outputId": "eec774be-f476-4284-a0f7-2c43f365ff7b"
   },
   "outputs": [],
   "source": [
    "m = geemap.Map(center=[40, -100], zoom=4)\n",
    "dataset = ee.Image(\"USGS/NLCD_RELEASES/2021_REL/NLCD/2021\")\n",
    "landcover = dataset.select(\"landcover\")\n",
    "m.add_layer(landcover, {}, \"NLCD 2021\", True, 0.7)\n",
    "states = ee.FeatureCollection(\"TIGER/2018/States\").filterBounds(\n",
    "    ee.Geometry.BBox(-127, 23, -66, 50)\n",
    ")\n",
    "style = {\"fillColor\": \"00000000\"}\n",
    "m.add_layer(states.style(**style), {}, \"US States\")\n",
    "m.add_legend(title=\"NLCD Land Cover\", builtin_legend=\"NLCD\")\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "TtGBFHzl4U6P"
   },
   "source": [
    "Calculate the total area of each land cover type for each state."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "-PygT2Rj4U6P",
    "outputId": "4da90380-b163-4ba9-adea-92488474d8f2"
   },
   "outputs": [],
   "source": [
    "landcover_stats = geemap.zonal_stats_by_group(\n",
    "    landcover,\n",
    "    states,\n",
    "    stats_type=\"SUM\",\n",
    "    scale=1000,\n",
    "    denominator=1e6,  # Convert the unit to sq. km\n",
    "    decimal_places=2,\n",
    "    return_fc=True,\n",
    "    verbose=False,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Pde1kXte4U6Q"
   },
   "source": [
    "Convert the result to a Pandas DataFrame."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 236
    },
    "id": "44YlIWeZ4U6Q",
    "outputId": "232e24b7-4d94-4001-87ed-054dcbc33d56"
   },
   "outputs": [],
   "source": [
    "landcover_df = geemap.ee_to_df(landcover_stats)\n",
    "landcover_df.sort_values(\"Class_82\", ascending=False).head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "CK23ABtK4U6Q"
   },
   "source": [
    "Create a bar chart to show the total area of crop land for each state."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 517
    },
    "id": "By9yGToj4U6Q",
    "outputId": "f37b5fc7-ba2a-47c5-cfd4-f6f9058766bb"
   },
   "outputs": [],
   "source": [
    "geemap.bar_chart(\n",
    "    landcover_df,\n",
    "    x=\"NAME\",\n",
    "    y=\"Class_82\",\n",
    "    x_label=\"State\",\n",
    "    y_label=\"Crop Area (km2)\",\n",
    "    title=\"Crop Area by State\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "QM5v68q94U6Q"
   },
   "source": [
    "Create a pie chart to show each state's contribution to the total crop area of the contiguous United States."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 617
    },
    "id": "zW3iNU9l4U6Q",
    "outputId": "f3b1b95b-7ea8-423b-c6a4-26e60dbbe4e5"
   },
   "outputs": [],
   "source": [
    "geemap.pie_chart(\n",
    "    landcover_df,\n",
    "    \"NAME\",\n",
    "    \"Class_82\",\n",
    "    title=\"Crop Area by State\",\n",
    "    height=600,\n",
    "    max_rows=30,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "2wRc57V-4U6Q"
   },
   "source": [
    "## To GeoPandas GeoDataFrame\n",
    "\n",
    "In addition to Pandas DataFrame, we can also convert an Earth Engine FeatureCollection to a GeoPandas GeoDataFrame. The `ee_to_gdf()` function is similar to the `ee_to_df()` function, but it returns a GeoPandas GeoDataFrame.\n",
    "\n",
    "Let's convert the feature collection resulting from the elevation zonal statistics above to a GeoPandas GeoDataFrame."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 206
    },
    "id": "6qs9socr4U6Q",
    "outputId": "f4631c4c-020e-4acc-d3b2-f2f0ab448759"
   },
   "outputs": [],
   "source": [
    "dem_gdf = geemap.ee_to_gdf(dem_stats)\n",
    "dem_gdf.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "MjIxTKpz4U6Q"
   },
   "source": [
    "Create a choropleth map to show the mean elevation for each state."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "rbGRl0U_4U6R",
    "outputId": "a6554bc0-e24f-4b7e-8fd5-2633281e3467"
   },
   "outputs": [],
   "source": [
    "if not in_colab_shell():  # This code block does not work well in Colab. Skip it\n",
    "    m = geemap.Map(center=[40, -100], zoom=4)\n",
    "    m.add_data(\n",
    "        dem_gdf,\n",
    "        column=\"mean\",\n",
    "        cmap=\"terrain\",\n",
    "        scheme=\"Quantiles\",\n",
    "        k=10,\n",
    "        layer_name=\"Mean Elevation\",\n",
    "        legend_title=\"Mean Elevation (m)\",\n",
    "    )\n",
    "    m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "mW9hs2DHAAgE"
   },
   "source": [
    "![](https://i.imgur.com/XioEMRN.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "_h-raLnf4U6R"
   },
   "source": [
    "Save the GeoDataFrame to a GeoJSON file."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "3OZiBra64U6R",
    "outputId": "8955cfb6-1e29-416f-e331-57e76935386f"
   },
   "outputs": [],
   "source": [
    "dem_gdf.to_file(\"dem.geojson\", driver=\"GeoJSON\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "6lm4KX9w4U6R"
   },
   "source": [
    "Visualize the GeoJSON file in 3D using the pydeck mapping backend."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "iun6o4BJ4U6R",
    "outputId": "4325cba4-51c0-4d02-e685-8a2b8e339685"
   },
   "outputs": [],
   "source": [
    "import geemap.deck as geemap"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "4wjKpOCZ4U6R",
    "outputId": "491fb863-6a1c-457a-9fdd-08927bb2211f"
   },
   "outputs": [],
   "source": [
    "if not in_colab_shell():  # This code block does not work well in Colab. Skip it\n",
    "    initial_view_state = {\n",
    "        \"latitude\": 40,\n",
    "        \"longitude\": -100,\n",
    "        \"zoom\": 3,\n",
    "        \"pitch\": 45,\n",
    "        \"bearing\": 10,\n",
    "    }\n",
    "    m = geemap.Map(initial_view_state=initial_view_state)\n",
    "    m.add_vector(\n",
    "        \"dem.geojson\",\n",
    "        extruded=True,\n",
    "        get_elevation=\"mean\",\n",
    "        get_fill_color=\"[mean / 10, mean / 10, 0]\",\n",
    "        elevation_scale=100,\n",
    "    )\n",
    "    m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "l0hoS43kBPts"
   },
   "source": [
    "![](https://i.imgur.com/pQo7OkQ.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "KfHYZHGc4U6V"
   },
   "source": [
    "## To Dask DataFrame\n",
    "\n",
    "[Dask DataFrame](https://docs.dask.org/en/stable/dataframe.html) helps you process large tabular data by parallelizing pandas, either on your laptop for larger-than-memory computing, or on a distributed cluster of computers.\n",
    "\n",
    "The [dask-ee](https://github.com/alxmrs/dask-ee) Python package provides a bridge between Dask and Google Earth Engine. It allows you to use Dask to process Earth Engine vector data, which can be useful for large-scale data processing."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "dB5xOYGA4U6V",
    "outputId": "516c8a30-30ee-433a-c9f5-f78b189f801e"
   },
   "outputs": [],
   "source": [
    "import dask_ee\n",
    "import geemap"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "hyYZeodm4U6V"
   },
   "source": [
    "Let's use the [Global Power Plant Database](https://developers.google.com/earth-engine/datasets/catalog/WRI_GPPD_power_plants) as an example."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 621,
     "referenced_widgets": [
      "fc6d4533abbf4d28abc4aa6c6f2b0133",
      "e083db3daa624d14b86353670c024943",
      "c11d8bf018c5451b913b11da4a7478f8",
      "5a166c054ea148c3bd6e66e9ee49f23a",
      "9c633160a651447f9a76de7e97064745",
      "d05b3ab91a774aae905f80ee39dd99d4",
      "deb9606039c54bf7860bb8ecbecf595d",
      "edc33d9bea594c0c87e2961a4f4ebb46",
      "1379528f36c146ef83de24ec66649c39",
      "941774bd1150471a92bca70a3197ee3f",
      "14c7a98a77624313bb21b1c7c64af30f",
      "1a824d986e3a4be3bcdd1b0624f289b2",
      "c5b15a4a03fd43f6bb2e4b40018e88b2",
      "0544a5ec4f5f40fea111721524f37642",
      "c2c9382afa054259b0edca75b488558d",
      "85c94ad9326b4004aa9e053fa09261f1",
      "2f5f2bf54cb448f6a1075109c0945a8e",
      "1856cd0ab4e943199bf15fc5682691a5",
      "af4c32ca0e9f442a8f790c5e24583c85",
      "09249a4cd14b4863b30c172dd2142d41",
      "1919e772ff5b4692bb2214bf3fa26d2f",
      "898630442c30479a9dbdb7b9a3c13ce8",
      "8bf3bbef9ac848b7927303f03f8cb9e8",
      "13cc1021e26a4e7589ba8b027f5cb68e",
      "26a2884290694b38a22f3e8f841d61e0",
      "166eea6e40e94fbbae01876888f27f77",
      "caed663876f94ca781892067545234d4",
      "1b3e083134d84a69b3dd39c9ce10cf8e",
      "d126ee54a2a14964b0e76b5944e3cfc9",
      "c60f0d45b37b4264a98b7a39bef28486",
      "438f1ecb7b264d66b353cc0b1c1056fd",
      "9ed12e710f884248aff0e306b7cd26e1",
      "7acb5f65e8fb4458b891fe3bf9491d83",
      "7016b3e8d9b24173af27a815df681e39",
      "ecf43be4702e4116aed19ae65dffdc03",
      "a1c946fe15184e1c9d65af4ade4b4474",
      "85f23a6b0530496a8c478133cb596689",
      "d24d05c9c83d4a5f99e7c92f6225b7ff",
      "d3dfb7bd6cbe445eb5f09660bd857b2b",
      "f8ef37e7cb124af9a099087d10408c01",
      "afe0972d37e946f9b6ce8822586eb3f1",
      "ecbe50a5f97246f5a6cd468ed40f5e1d"
     ]
    },
    "id": "-eBlJ9yv4U6V",
    "outputId": "184c1b22-c7e2-4838-8823-7d8dd22b1454"
   },
   "outputs": [],
   "source": [
    "fuels = [\n",
    "    \"Coal\",\n",
    "    \"Oil\",\n",
    "    \"Gas\",\n",
    "    \"Hydro\",\n",
    "    \"Nuclear\",\n",
    "    \"Solar\",\n",
    "    \"Waste\",\n",
    "    \"Wind\",\n",
    "    \"Geothermal\",\n",
    "    \"Biomass\",\n",
    "]\n",
    "colors = [\n",
    "    \"000000\",\n",
    "    \"593704\",\n",
    "    \"BC80BD\",\n",
    "    \"0565A6\",\n",
    "    \"E31A1C\",\n",
    "    \"FF7F00\",\n",
    "    \"6A3D9A\",\n",
    "    \"5CA2D1\",\n",
    "    \"FDBF6F\",\n",
    "    \"229A00\",\n",
    "]\n",
    "fc = ee.FeatureCollection(\"WRI/GPPD/power_plants\").filter(\n",
    "    ee.Filter.inList(\"fuel1\", fuels)\n",
    ")\n",
    "styled_fc = geemap.ee_vector_style(fc, column=\"fuel1\", labels=fuels, color=colors)\n",
    "m = geemap.Map(center=[40, -100], zoom=4)\n",
    "m.add_layer(styled_fc, {}, \"Power Plants\")\n",
    "m.add_legend(title=\"Power Plant Fuel Type\", labels=fuels, colors=colors)\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "bDXljFBS4U6V"
   },
   "source": [
    "Convert the Earth Engine FeatureCollection to a Dask DataFrame using the `read_ee()` function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 272
    },
    "id": "Ww2SIX4i4U6V",
    "outputId": "469b93b8-f1aa-4603-c8a2-e4ac424eabb3"
   },
   "outputs": [],
   "source": [
    "df = dask_ee.read_ee(\"WRI/GPPD/power_plants\")\n",
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "AAHYnfgq4U6V"
   },
   "source": [
    "Note that the Dask dataframe above only shows the structure of our feature collection - the columns and datatypes, but no actual data has been loaded yet. To load the data, we can use the `compute()` method."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 322
    },
    "id": "kYHdAE2r4U6W",
    "outputId": "db6a74b9-0712-4b96-b4b6-b3696e829c96"
   },
   "outputs": [],
   "source": [
    "df.compute().head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "v16KLyac4U6W"
   },
   "source": [
    "Plot the total capacity of coal and wind plants in the United States, by year of commissioning."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 467
    },
    "id": "sOGDrjLK4U6W",
    "outputId": "df69853d-91bd-43ed-ea42-559a4a5532a0"
   },
   "outputs": [],
   "source": [
    "(\n",
    "    df[df.comm_year.gt(1940) & df.country.eq(\"USA\") & df.fuel1.isin([\"Coal\", \"Wind\"])]\n",
    "    .astype(\n",
    "        {\"comm_year\": int}\n",
    "    )  # Year of plant operation, weighted by unit-capacity when data is available\n",
    "    .drop(columns=[\"geo\"])\n",
    "    .groupby([\"comm_year\", \"fuel1\"])\n",
    "    .agg({\"capacitymw\": \"sum\"})  # \tElectrical generating capacity in megawatts\n",
    "    .reset_index()\n",
    "    .sort_values(by=[\"comm_year\"])\n",
    "    .compute(scheduler=\"threads\")\n",
    "    .pivot_table(index=\"comm_year\", columns=\"fuel1\", values=\"capacitymw\", fill_value=0)\n",
    "    .plot()\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "D8H1GKGD4U6W"
   },
   "source": [
    "## To NumPy Array\n",
    "\n",
    "To convert an Earth Engine Image to a NumPy array, we can use the `ee_to_numpy()` function, which uses `ee.data.computePixels()` under the hood.\n",
    "\n",
    "Let's add a Landsat satellite image to the map."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 621,
     "referenced_widgets": [
      "c9bbf29ee8034d62b1022273f49242a4",
      "1b96e0e5e7b3494ca00203d08078d36c",
      "b622d2fd246549a68a798cab9c6fa320",
      "485aee285be6414c81ca81c281499f83",
      "f6deb32d437c477992718090919913c7",
      "228f168f79c64550841ca82ea65f8594",
      "e99f9524aec0406ba3a2aec9d7003e4b",
      "d99dca7e012442db866b3d9f7e432374",
      "3a115e2b60b04e35b6766b0699ed6b51",
      "68a772b8eab44f8fb46c02c0eb0d36ae",
      "541f89b343714d5f92504b00d9c2363b",
      "a568b4897c30441ca6c6fa480767ea42",
      "9cc3fed0284545edacf1eb1ad99759d0",
      "70e422aa5a4c49359d983fabacbcd708",
      "d533e5091d5c4980ae64d88c2b967e31",
      "21d08c2c76184bd1a84f48d931f20dcd",
      "328163d793f4428f8cdea3b6a2ecbf57",
      "642b8cf81c7b4ad09ea3141be441fc2a",
      "cc15ac69f0a14ce398107d1b15472e15",
      "98c14760d2014198a58f2a971370083a",
      "3f813d71c30a4670a066009d68f230df",
      "0a050436658b4952852f1bb24cd662bb",
      "9fa8a4b2cf1548c5b2bf3cd45282c4ba",
      "d43faccff6ce49999f7c35a7ff407734",
      "0e7400393bd3467fa1cdc58f872429fd",
      "36eb5d2b5f564d6b86ad6f9575b8741c"
     ]
    },
    "id": "xeXzbppW4U6W",
    "outputId": "2b601767-8c70-4c17-d8f0-3197bb395c9f"
   },
   "outputs": [],
   "source": [
    "m = geemap.Map()\n",
    "\n",
    "image = ee.Image(\"LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318\").select(\n",
    "    [\"B5\", \"B4\", \"B3\"]\n",
    ")\n",
    "\n",
    "vis_params = {\"min\": 0, \"max\": 0.5, \"gamma\": [0.95, 1.1, 1]}\n",
    "\n",
    "m.center_object(image, 8)\n",
    "m.add_layer(image, vis_params, \"Landsat\")\n",
    "\n",
    "region = ee.Geometry.BBox(-122.5955, 37.5339, -122.0982, 37.8252)\n",
    "fc = ee.FeatureCollection(region)\n",
    "style = {\"color\": \"ffff00ff\", \"fillColor\": \"00000000\"}\n",
    "m.add_layer(fc.style(**style), {}, \"ROI\")\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "wVepW5I64U6W"
   },
   "source": [
    "Convert a subset of the image to a NumPy array using the `ee_to_numpy()` function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "mptmNy054U6W",
    "outputId": "05669568-3488-4d35-8b90-713fc9146b17"
   },
   "outputs": [],
   "source": [
    "region = ee.Geometry.BBox(-122.5955, 37.5339, -122.0982, 37.8252)\n",
    "rgb_img = geemap.ee_to_numpy(image, region=region)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 35
    },
    "id": "BaZ3S2vW4U6W",
    "outputId": "6009448d-e84f-41a7-9ca6-0b4e9681cc3d"
   },
   "outputs": [],
   "source": [
    "print(rgb_img.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "qdfTWrcG4U6X"
   },
   "source": [
    "Display the NumPy array using Matplotlib."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 433
    },
    "id": "BzESsQV_4U6X",
    "outputId": "e71b8211-adfc-49a5-cff7-b5e4c3f99ef8"
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "rgb_img_test = (255 * ((rgb_img[:, :, 0:3]) + 0.2)).astype(\"uint8\")\n",
    "plt.imshow(rgb_img_test)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "YiuDG4wk4U6X"
   },
   "source": [
    "## To Xarray Dataset\n",
    "\n",
    "The [Xee](https://github.com/google/Xee) Python package provides a bridge between Xarray and Google Earth Engine. It allows you to convert Earth Engine Image objects to Xarray DataArray objects.\n",
    "\n",
    "In this section, we will use the [ERA5 hourly data](https://developers.google.com/earth-engine/datasets/catalog/ECMWF_ERA5_LAND_HOURLY) to demonstrate how to convert an Earth Engine ImageCollection to an Xarray Dataset.\n",
    "\n",
    "NASA reported that July 2023 as Hottest Month on Record Ever Since 1880 ([source](https://www.nasa.gov/news-release/nasa-clocks-july-2023-as-hottest-month-on-record-ever-since-1880)). Let's use Google Earth Engine to retrieve the temperature data for July 2023.\n",
    "\n",
    "![](https://www.nasa.gov/wp-content/uploads/2023/08/microsoftteams-image_26.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "YCHqbIFp4U6X"
   },
   "source": [
    "First, let's filter the ERA5 hourly data for July 2023 and select the temperature band."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 621,
     "referenced_widgets": [
      "a34ab5acc60c4dfe87c3b54cf944b1af",
      "4830d28170ff43288e202d387aeb7f97",
      "5f8d120a641a4ad8a3ff4142312c1134",
      "6a85e01385564a4dac37c341f7dc6f04",
      "699535ccba444136afe346f5465e4aca",
      "90ee99cab10f4a1da9ab7120bdd8dd21",
      "387ea340c1954de1907f8e38b1e71d14",
      "2a0206203ff7481189795af60c380ee9",
      "205278393d70465b8f38d026978e9fcb",
      "cb66f8fb3559458b85125a2b412a19b3",
      "8b7cbaa3fece49c9939ecb751a24cdb0",
      "502bf0cb70d34de18aa521d8de144922",
      "594d3331e1e145b5942242bd0878b9fc",
      "dc5b882076224495b5e1c24e040d275e",
      "2dbf3865b30940f79f1cd52b408adef1",
      "bd8d1db895084bf69f1f2bbe91ac29f9",
      "fcddf6d6fda645faba86c2db3ecce9f4",
      "4bcde92fe4d1490999819ef4eaebd63e",
      "19e270d1495a4fcd8fea2d39887eb58b",
      "c9428e6e761f4301af7205eee5794dbe",
      "c6c6151735d54f88918ed386702a4bd6",
      "d2eca46532c5457faa2841eed5a419f1",
      "7562c0ec7c6648d6bb34a304d185c132",
      "82370c6e118b4d6e9fd2ced7d46d5451",
      "81e6e83fa54c4c3c84ec845a7d156b9f",
      "647c647caaa546dc94df13f0039a5e2e",
      "a1794a60832b48c087e510c945129cb0",
      "607d1ad5d1c54e2db7893c5c23de71ae"
     ]
    },
    "id": "QdScwO154U6X",
    "outputId": "cd86bf6c-0398-4fd7-fae0-aa2f3240403d"
   },
   "outputs": [],
   "source": [
    "m = geemap.Map(center=[40, -100], zoom=4)\n",
    "dataset = (\n",
    "    ee.ImageCollection(\"ECMWF/ERA5_LAND/HOURLY\")\n",
    "    .filter(ee.Filter.date(\"2023-07-01\", \"2023-08-01\"))\n",
    "    .select(\"temperature_2m\")\n",
    ")\n",
    "temp = dataset.mean()\n",
    "temp_vis = {\"min\": 270, \"max\": 310, \"palette\": \"coolwarm\"}\n",
    "m.add_layer(temp, temp_vis, \"Temperature\")\n",
    "m.add_colorbar(temp_vis, label=\"Temperature (K)\", layer_name=\"Temperature\")\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "rHbGuFOk4U6X"
   },
   "source": [
    "To convert the ImageCollection to an Xarray Dataset, let's initialize EE with the high-volume endpoint."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "rxisow8J4U6X",
    "outputId": "541cf049-e91c-48b4-d18a-55b87030298c"
   },
   "outputs": [],
   "source": [
    "url = \"https://earthengine-highvolume.googleapis.com\"\n",
    "ee.Initialize(url=url, project=EE_PROJECT_ID)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "TnrGrq2T4U6X"
   },
   "source": [
    "Now, we can convert the ImageCollection to an Xarray Dataset using the `geemap.ee_to_xarray()` function, which uses xee under the hood."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 270
    },
    "id": "fETMPBfy4U6X",
    "outputId": "8b0f6810-543c-4efe-d1ac-8cadb9c6f597"
   },
   "outputs": [],
   "source": [
    "ds = geemap.ee_to_xarray(dataset, n_images=-1, ee_initialize=False)\n",
    "ds"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "_Qh1E3Ck4U6Y"
   },
   "source": [
    "We can see that the xarray dataset has three dimensions: time, lon, and lat. The time dimension has 744 elements, which is the number of hours in the month of July 2023. The lon and lat dimensions are the number of pixels in the x and y directions, respectively. The dataset has one variable: `temperature_2m`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "vEnXI8uF4U6Y",
    "outputId": "8d03d7ce-0562-480d-c62d-e4d0b9b65bed"
   },
   "outputs": [],
   "source": [
    "da = ds[\"temperature_2m\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "nU7EUele4U6Y"
   },
   "source": [
    "Plot the first time step of the temperature data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 582
    },
    "id": "aopa3B3R4U6Y",
    "outputId": "b6a91f01-8989-4986-8c7c-baaf63db4c9d"
   },
   "outputs": [],
   "source": [
    "da.isel(time=1).plot(x=\"lon\", y=\"lat\", aspect=2, size=6, cmap=\"coolwarm\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "044Wlbgk4U6Y"
   },
   "source": [
    "Select the temperature data for July 1, 2023, 12:00:00 AM UTC and the horizontal profiles of the temperature data at different latitudes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 545
    },
    "id": "K03jLjV24U6Y",
    "outputId": "421d093c-f230-46a7-dfd4-894898e8a99b"
   },
   "outputs": [],
   "source": [
    "da.isel(time=1).sel(lat=[10, 30, 50, 70], method=\"nearest\").plot(x=\"lon\", hue=\"lat\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "UYnKrQjk4U6Y"
   },
   "source": [
    "Calculate the mean temperature for July 2023."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 560
    },
    "id": "Y_TqvcLu4U6Y",
    "outputId": "a0db7844-6e09-457e-bcf8-efb01cd592bb"
   },
   "outputs": [],
   "source": [
    "da.mean(dim=\"time\").plot(x=\"lon\", y=\"lat\", aspect=2, size=6, cmap=\"coolwarm\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "jRUNKl5v4U6Y"
   },
   "source": [
    "Select daily images at 16:00:00 AM UTC (12 PM EST) in July 2023."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 35
    },
    "id": "xipjNJwo4U6Z",
    "outputId": "03f3dcc0-5eb0-4a60-e881-442120735894"
   },
   "outputs": [],
   "source": [
    "time_at_16 = da.sel(time=da[\"time\"].dt.hour == 16)\n",
    "time_at_16.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "D9CwmoP24U6Z"
   },
   "source": [
    "Calculate the mean temperature at 12 PM EST for July 2023."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 565
    },
    "id": "DFqjav4r4U6Z",
    "outputId": "0a1e35e1-de9c-4307-fed9-ddba02a15396"
   },
   "outputs": [],
   "source": [
    "time_at_16.mean(dim=\"time\").plot(x=\"lon\", y=\"lat\", aspect=2, size=6, cmap=\"coolwarm\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "iVmDDSI24U6Z"
   },
   "source": [
    "Select monthly images at 16:00:00 AM UTC (12 PM EST) in 2023."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "rPB-4dUr4U6Z",
    "outputId": "a182bb16-703c-4242-fc61-c333600bbe02"
   },
   "outputs": [],
   "source": [
    "dataset = (\n",
    "    ee.ImageCollection(\"ECMWF/ERA5_LAND/HOURLY\")\n",
    "    .filter(ee.Filter.date(\"2023-01-01\", \"2024-01-01\"))\n",
    "    .filter(ee.Filter.calendarRange(1, 1, \"day_of_month\"))\n",
    "    .filter(ee.Filter.calendarRange(16, 16, \"hour\"))\n",
    "    .select(\"temperature_2m\")\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "6ZMQCpN84U6Z"
   },
   "source": [
    "Convert the monthly images to an Xarray Dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 270
    },
    "id": "OgTzZBj94U6Z",
    "outputId": "ed053d0d-c61e-4cf3-930b-9baeedba30de"
   },
   "outputs": [],
   "source": [
    "ds = geemap.ee_to_xarray(dataset, n_images=-1, ee_initialize=False)\n",
    "ds"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "eG8vddGq4U6Z"
   },
   "source": [
    "Select the temperature variable from the dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "qiaZptjv4U6a",
    "outputId": "fe1e861f-f89f-4cc0-c3b5-77f3fae5bf74"
   },
   "outputs": [],
   "source": [
    "monthly_da = ds[\"temperature_2m\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "3FaM81bv4U6a"
   },
   "source": [
    "Plot the temperature data for the first date of each month in 2023."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 1000
    },
    "id": "GF3VHkPX4U6a",
    "outputId": "7ccb7086-b295-4bea-b1c4-5236e4e7afc1"
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "fig, axes = plt.subplots(nrows=4, ncols=3, figsize=(20, 15))\n",
    "axes = axes.flatten()\n",
    "cbar_ax = fig.add_axes([0.92, 0.3, 0.01, 0.4])\n",
    "\n",
    "for i, time in enumerate(monthly_da.time):\n",
    "    data = monthly_da.isel(time=i)\n",
    "    im = data.plot(ax=axes[i], x=\"lon\", y=\"lat\", cmap=\"coolwarm\", add_colorbar=False)\n",
    "    axes[i].set_aspect(aspect=\"equal\")\n",
    "    axes[i].set_title(str(time.values)[:10])\n",
    "\n",
    "fig.colorbar(im, cax=cbar_ax)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "YkcdYRn64U6a"
   },
   "source": [
    "## 3D visualization\n",
    "\n",
    "The [HyperCoast](https://hypercoast.org) Python package provides some functions to visualize Xarray datasets in 3D using [PyVista](https://pyvista.org). Note that the PyVista 3D visualization backend does not work in Google Colab ([source](https://tutorial.pyvista.org/getting-started.html#google-colab)). However, you can uncomment the following two code blocks to enable static plotting in Google Colab."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "CsCSSzFL4U6a",
    "outputId": "7ad25d5e-dac4-4bc4-e08c-2e7492151a7c"
   },
   "outputs": [],
   "source": [
    "# !apt-get install -qq xvfb libgl1-mesa-glx\n",
    "# !pip install pyvista -qq"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "r0NI36rl4U6a",
    "outputId": "107a493b-0fd1-4f19-ed1c-fd407c48079e"
   },
   "outputs": [],
   "source": [
    "# import pyvista\n",
    "\n",
    "# pyvista.set_jupyter_backend('static')\n",
    "# pyvista.global_theme.notebook = True\n",
    "# pyvista.start_xvfb()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "U3R4ilhr4U6a",
    "outputId": "9616fd85-3370-4f6d-e76e-fdc443158b2b"
   },
   "outputs": [],
   "source": [
    "import hypercoast"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "W_Fu_h0r4U6a"
   },
   "source": [
    "First, we need to transpose the Xarray Dataset to have the time dimension as the last dimension."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "ht8K3B-I4U6a",
    "outputId": "bf29bfd8-b93a-4960-bb20-ce5aeea65bbb"
   },
   "outputs": [],
   "source": [
    "ds = ds.transpose(\"lat\", \"lon\", \"time\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 270
    },
    "id": "gB_OTJ_9_FDI",
    "outputId": "cf8dcea5-5abd-44e8-92eb-6c70d94d8327"
   },
   "outputs": [],
   "source": [
    "ds"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ayKvQMIf4U6a"
   },
   "source": [
    "Visualize the monthly temperature data in 3D."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "2lV5gYws4U6b",
    "outputId": "92490e4e-084e-42c0-86cc-95a06a01232d"
   },
   "outputs": [],
   "source": [
    "if not in_colab_shell():  # This code block does not work well in Colab. Skip it\n",
    "    p = hypercoast.image_cube(\n",
    "        ds,\n",
    "        variable=\"temperature_2m\",\n",
    "        clim=(270, 310),\n",
    "        title=\"Temperature\",\n",
    "        cmap=\"coolwarm\",\n",
    "        grid_spacing=(1, 1, 3),\n",
    "    )\n",
    "    p.camera_position = [\n",
    "        (-479.09, -82.89, -444.45),\n",
    "        (89.5, 179.5, 16.5),\n",
    "        (0.58, 0.14, -0.80),\n",
    "    ]\n",
    "    p.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "7E-xGnOf4U6b"
   },
   "source": [
    "![](https://i.imgur.com/0AH5k1F.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "t54xrri04U6b"
   },
   "source": [
    "Interactive thresholding of the temperature data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 17
    },
    "id": "GEbQ6xVL4U6b",
    "outputId": "53695f32-6154-4f22-aab8-cfb0eb9066da"
   },
   "outputs": [],
   "source": [
    "if not in_colab_shell():  # This code block does not work well in Colab. Skip it\n",
    "    p = hypercoast.image_cube(\n",
    "        ds,\n",
    "        variable=\"temperature_2m\",\n",
    "        clim=(270, 310),\n",
    "        title=\"Temperature\",\n",
    "        cmap=\"coolwarm\",\n",
    "        widget=\"threshold\",\n",
    "    )\n",
    "    p.camera_position = [\n",
    "        (-479.09, -82.89, -444.45),\n",
    "        (89.5, 179.5, 16.5),\n",
    "        (0.58, 0.14, -0.80),\n",
    "    ]\n",
    "    p.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ETnWQ9Ad4U6b"
   },
   "source": [
    "![](https://i.imgur.com/qaKkmKX.gif)"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
